<?php declare(strict_types=1);


namespace App\Lib\Migrate;


use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Bean\Annotation\Mapping\Inject;
use Swoft\Db\Pool;
use Swoft\Devtool\Helper\ConsoleHelper;
use Swoft\Devtool\Migration\Exception\MigrationException;
use App\Lib\Migrate\MigrateLogic;
use Throwable;

/**
 * Manage swoft project database migration commands[by <cyan>devtool</cyan>]
 *
 * 迁移程序目前支持uph和down，其他由于时间问题未做测试
 *
 * @since 2.0
 *
 * @Bean()
 *
 */
class Migrate
{
    /**
     * @Inject()
     *
     * @var MigrateLogic
     */
    private $logic;

    /**
     * Creates a new migration.
     *
     * CommandArgument(name="name", desc="the name of the new migration", type="string", mode=Command::OPT_REQUIRED)
     * @param array $data
     * @return string|void
     */
    public function create($data = [])
    {
        try {
            $name = (string)isset($data['name'])?$data['name']:'';
            $isConfirm = true;

            if (empty($name)) {
                throw new MigrationException("name param can't be empty");
            }
            return $this->logic->create($name, (bool)$isConfirm);
        } catch (Throwable $e) {
            output()->error($e->getMessage());
            ConsoleHelper::highlight($e->getTraceAsString());
        }
    }

    /**
     * Upgrades the application by applying new migrations.
     *
     * CommandMapping()
     * CommandArgument(name="name", desc="database migrate names. Can be prefix , Many is separated by ','", type="string")
     * CommandOption(name="name", desc="database migrate names. Can be prefix , Many is separated by ','", type="string")
     * @param array $data
     * @return string
     */
    public function up($data = [])
    {

        [$dbs, $prefix, $start, $end, $isConfirm] = $this->getPublicParams($data);

        $name = (string)isset($data['name'])?$data['name']:'';
        $names = $name ? explode(',', $name) : [];

        try {
            //这里修改了原来代码直接默认不要求用户确认
            return $this->logic->up($names, $dbs, $prefix, $start, $end, $isConfirm = true);
        } catch (Throwable $e) {
            output()->error($e->getMessage());
            ConsoleHelper::highlight($e->getTraceAsString());
        }
    }

    /**
     * Downgrades the application by reverting old migrations.
     *
     * CommandMapping()
     * CommandArgument(name="name", desc="database migrate names. Can be prefix , Many is separated by ','", type="string")
     * CommandOption(name="pool", desc="choose default database pool", type="string", default="db.pool")
     * CommandOption(name="step", desc="rollback file step", type="int", default="1")
     * @param array $data
     * @return string
     */
    public function down($data = [])
    {
        [$dbs, $prefix, $start, $end, $isConfirm] = $this->getPublicParams($data);

        $name = (string)isset($data['name'])?$data['name']:'';
        $pool = (string)isset($data['pool'])?$data['pool']:Pool::DEFAULT_POOL;
        $step = (int)isset($data['step'])?$data['step']:1;

        $names = $name ? explode(',', $name) : [];

        try {
            return $this->logic->down($names, $dbs, $prefix, $start, $end, $isConfirm, $pool, $step);
        } catch (Throwable $e) {
            output()->error($e->getMessage());
            ConsoleHelper::highlight($e->getTraceAsString());
        }
    }

    /**
     * Displays the migration history.
     * @param array $data
     */
    public function history($data = []): void
    {
        [$dbs, $prefix, $start, $end,] = $this->getPublicParams($data);

        $limit = (int)input()->get('limit', 10);
        $pool = (string)input()->getOpt('pool', Pool::DEFAULT_POOL);

        try {
            $this->logic->history($dbs, $prefix, $start, $end, $limit, $pool);
        } catch (Throwable $e) {
            output()->error($e->getMessage());
            ConsoleHelper::highlight($e->getTraceAsString());
        }
    }

    /**
     * @param array $data
     * @return array
     */
    private function getPublicParams($data = []): array
    {
        $db = $data['db']??'';
        $prefix = $data['prefix']??'';
        $start = $data['start']??'';
        $end = $data['end']??'';
        $isConfirm = $data['y']??true;

        $dbs = $db ? explode(',', $db) : [];

        return [$dbs, (string)$prefix, (int)$start, (int)$end, (bool)$isConfirm];
    }
}
